home *** CD-ROM | disk | FTP | other *** search
/ PsL Monthly 1993 December / PSL Monthly Shareware CD-ROM (December 1993).iso / prgmming / dos / pascal / bfloat.com / BFLOAT.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1989-05-14  |  8.6 KB  |  295 lines

  1. {$A-,B-,D-,E+,F-,I-,L-,N+,O-,R-,S-,V-}
  2. unit BFLOAT;
  3. (*
  4.             MicroSoft Binary Float to IEEE format Conversion
  5.                     Copyright (c) 1989 J.P. Ritchey
  6.                             Version 1.0
  7.  
  8.          This software is released to the public domain.  Though
  9.          tested, there could be some errors.  Any reports of bugs
  10.          discovered would be appreciated. Send reports to
  11.                  Pat Ritchey     Compuserve ID 72537,2420
  12. *)
  13. interface
  14.  
  15. type
  16.   bfloat4 = record
  17.     { M'Soft single precision }
  18.     mantissa : array[5..7] of byte;
  19.     exponent : byte;
  20.     end;
  21.  
  22.   Bfloat8 = record
  23.     { M'Soft double precision }
  24.     mantissa : array[1..7] of byte;
  25.     exponent : byte;
  26.     end;
  27.  
  28.  
  29. Function Bfloat4toExtended(d : bfloat4) : extended;
  30. Function Bfloat8toExtended(d : Bfloat8): extended;
  31.  
  32. { These routines will convert a MicroSoft Binary Floating point
  33.   number to IEEE extended format.  The extended is large enough
  34.   to store any M'Soft single or double number, so no over/underflow
  35.   problems are encountered.  The Mantissa of an extended is large enough
  36.   to hold a BFloatx mantissa, so no truncation is required.
  37.  
  38.   The result can be returned to TP single and double variables and
  39.   TP will handle the conversion.  Note that Over/Underflow can occur
  40.   with these types. }
  41.  
  42. Function HexExt(ep:extended) : string;
  43.  
  44. { A routine to return the hex representation of an IEEE extended variable
  45.   Left in from debugging, you may find it useful }
  46.  
  47. Function ExtendedtoBfloat4(ep : extended; var b : bfloat4) : boolean;
  48. Function ExtendedtoBfloat8(ep : extended; var b : Bfloat8) : boolean;
  49.  
  50. { These routines are the reverse of the above, that is they convert
  51.   TP extended => M'Soft format.  You can use TP singles and doubles
  52.   as the first parameter and TP will do the conversion to extended
  53.   for you.
  54.  
  55.   The Function result returns True if the conversion was succesful,
  56.   and False if not (because of overflow).
  57.  
  58.   Since an extended can have an exponent that will not fit
  59.   in the M'Soft format Over/Underflow is handled in the following
  60.   manner:
  61.     Overflow:  Set the Bfloatx to 0 and return a False result.
  62.     Underflow: Set the BFloatx to 0 and return a True Result.
  63.  
  64.   No rounding is done on the mantissa.  It is simply truncated to
  65.   fit. }
  66.  
  67.  
  68. Function BFloat4toReal(b:bfloat4) : Real;
  69. Function BFloat8toReal(b:bfloat8) : Real;
  70.  
  71. { These routines will convert a MicroSoft Binary Floating point
  72.   number to Turbo real format.  The real is large enough
  73.   to store any M'Soft single or double Exponent, so no over/underflow
  74.   problems are encountered.  The Mantissa of an real is large enough
  75.   to hold a BFloat4 mantissa, so no truncation is required.  The
  76.   BFloat8 mantissa is truncated (from 7 bytes to 5 bytes) }
  77.  
  78. Function RealtoBFloat4(rp: real; var b:bfloat4) : Boolean;
  79. Function RealtoBFloat8(rp : real; var b:bfloat8) : Boolean;
  80.  
  81. { These routines do the reverse of the above.  No Over/Underflow can
  82.   occur, but truncation of the mantissa can occur
  83.   when converting Real to Bfloat4 (5 bytes to 3 bytes).
  84.  
  85.   The function always returns True, and is structured this way to
  86.   function similar to the IEEE formats }
  87.  
  88. implementation
  89. type
  90.   IEEEExtended = record
  91.      Case integer of
  92.      0 : (Mantissa : array[0..7] of byte;
  93.           Exponent : word);
  94.      1 : (e : extended);
  95.      end;
  96.  
  97.   TurboReal = record
  98.      Case integer of
  99.      0 : (Exponent : byte;
  100.           Mantissa : array[3..7] of byte);
  101.      1 : (r : real);
  102.      end;
  103.  
  104. Function HexExt(ep:extended) : string;
  105. var
  106.  e : IEEEExtended absolute ep;
  107.  i : integer;
  108.  s : string;
  109.  Function Hex(b:byte) : string;
  110.   const hc : array[0..15] of char = '0123456789ABCDEF';
  111.   begin
  112.   Hex := hc[b shr 4]+hc[b and 15];
  113.   end;
  114. begin
  115.   s := hex(hi(e.exponent))+hex(lo(e.exponent))+' ';
  116.   for i := 7 downto 0 do s := s+hex(e.mantissa[i]);
  117. HexExt := s;
  118. end;
  119.  
  120. Function NullMantissa(e : IEEEextended) : boolean;
  121. var
  122.  i : integer;
  123. begin
  124. NullMantissa := False;
  125. for i := 0 to 7 do if e.mantissa[i] <> 0 then exit;
  126. NullMantissa := true;
  127. end;
  128.  
  129. Procedure ShiftLeftMantissa(var e);
  130. { A routine to shift the 8 byte mantissa left one bit }
  131. inline(
  132. {0101} $F8/          {   CLC                        }
  133. {0102} $5F/          {   POP    DI                  }
  134. {0103} $07/          {   POP    ES                  }
  135. {0104} $B9/$04/$00/  {   MOV    CX,0004             }
  136. {0107} $26/$D1/$15/  {   RCL    Word Ptr ES:[DI],1  }
  137. {010A} $47/          {   INC    DI                  }
  138. {010B} $47/          {   INC    DI                  }
  139. {010C} $E2/$F9       {   LOOP   0107                }
  140. );
  141.  
  142. Procedure Normalize(var e : IEEEextended);
  143. { Normalize takes an extended and insures that the "i" bit is
  144.   set to 1 since M'Soft assumes a 1 is there. An extended has
  145.   a value of 0.0 if the mantissa is zero, so the first check.
  146.   The exponent also has to be kept from wrapping from 0 to $FFFF
  147.   so the "if e.exponent = 0" check.  If it gets this small
  148.   for the routines that call it, there would be underflow and 0
  149.   would be returned.
  150. }
  151. var
  152.  exp : word;
  153.  
  154. begin
  155. exp := e.exponent and $7FFF; { mask out sign }
  156. if NullMantissa(e) then
  157.    begin
  158.    E.exponent := 0;
  159.    exit
  160.    end;
  161. while e.mantissa[7] < 128 do
  162.    begin
  163.    ShiftLeftMantissa(e);
  164.    dec(exp);
  165.    if exp = 0 then exit;
  166.    end;
  167. e.exponent := (e.exponent and $8000) or exp;  { restore sign }
  168. end;
  169.  
  170. Function Bfloat8toExtended(d : Bfloat8) : extended;
  171. var
  172.   i : integer;
  173.   e : IEEEExtended;
  174. begin
  175.   fillchar(e,sizeof(e),0);
  176.   Bfloat8toExtended := 0.0;
  177.   if d.exponent = 0 then exit;
  178.   { if the bfloat exponent is 0 the mantissa is ignored and
  179.     the value reurned is 0.0 }
  180.   e.exponent := d.exponent - 129 + 16383;
  181.   { bfloat is biased by 129, extended by 16383
  182.     This creates the correct exponent }
  183.   if d.mantissa[7] > 127 then
  184.      { if the sign bit in bfloat is 1 then set the sign bit in the extended }
  185.      e.exponent := e.exponent or $8000;
  186.   move(d.Mantissa[1],e.mantissa[1],6);
  187.   e.mantissa[7] := $80 or (d.mantissa[7] and $7F);
  188.   { bfloat assumes 1.fffffff, so supply it for extended }
  189.   Bfloat8toExtended := e.e;
  190. end;
  191.  
  192. Function Bfloat4toExtended(d : bfloat4) : extended;
  193. var
  194.   i : integer;
  195.   e : IEEEExtended;
  196. begin
  197.   fillchar(e,sizeof(e),0);
  198.   Bfloat4toExtended := 0.0;
  199.   if d.exponent = 0 then exit;
  200.   e.exponent := integer(d.exponent - 129) + 16383;
  201.   if d.mantissa[7] > 127 then
  202.      e.exponent := e.exponent or $8000;
  203.   move(d.Mantissa[5],e.mantissa[5],2);
  204.   e.mantissa[7] := $80 or (d.mantissa[7] and $7F);
  205.   Bfloat4toExtended := e.e;
  206. end;
  207.  
  208. Function ExtendedtoBfloat8(ep : extended; var b : Bfloat8) : boolean;
  209. var
  210.   e : IEEEextended absolute ep;
  211.   exp : integer;
  212.   sign : byte;
  213. begin
  214. FillChar(b,Sizeof(b),0);
  215. ExtendedtoBfloat8 := true; { assume success }
  216. Normalize(e);
  217. if e.exponent = 0 then exit;
  218. sign := byte(e.exponent > 32767) shl 7;
  219. exp := (e.exponent and $7FFF) - 16383 + 129;
  220. if exp < 0 then exp := 0; { underflow }
  221. if exp > 255 then { overflow }
  222.    begin
  223.    ExtendedtoBfloat8 := false;
  224.    exit;
  225.    end;
  226. b.exponent := exp;
  227. move(e.mantissa[1],b.mantissa[1],7);
  228. b.mantissa[7] := (b.mantissa[7] and $7F) or sign;
  229. end;
  230.  
  231. Function ExtendedtoBfloat4(ep : extended; var b : Bfloat4) : boolean;
  232. var
  233.   e : IEEEextended absolute ep;
  234.   exp : integer;
  235.   sign : byte;
  236. begin
  237. FillChar(b,Sizeof(b),0);
  238. ExtendedtoBfloat4 := true; { assume success }
  239. Normalize(e);
  240. if e.exponent = 0 then exit;
  241. sign := byte(e.exponent > 32767) shl 7;
  242. exp := (e.exponent and $7FFF) - 16383 + 129;
  243. if exp < 0 then exp := 0; { underflow }
  244. if exp > 255 then { overflow }
  245.    begin
  246.    ExtendedtoBfloat4 := false;
  247.    exit;
  248.    end;
  249. b.exponent := exp;
  250. move(e.mantissa[5],b.mantissa[5],3);
  251. b.mantissa[7] := (b.mantissa[7] and $7F) or sign;
  252. end;
  253.  
  254. Function BFloat4toReal(b:bfloat4) : Real;
  255. var
  256.  r : TurboReal;
  257. begin
  258.   fillchar(r,sizeof(r),0);
  259.   r.exponent := b.exponent;
  260.   move(b.mantissa[5],r.mantissa[5],3);
  261.   Bfloat4toReal := r.r;
  262. end;
  263.  
  264. Function BFloat8toReal(b:bfloat8) : Real;
  265. var
  266.  r : TurboReal;
  267. begin
  268.   fillchar(r,sizeof(r),0);
  269.   r.exponent := b.exponent;
  270.   move(b.mantissa[3],r.mantissa[3],5);
  271.   Bfloat8toReal := r.r;
  272. end;
  273.  
  274. Function RealtoBFloat4(rp: real; var b:bfloat4) : Boolean;
  275. var
  276.  r : TurboReal absolute rp;
  277. begin
  278.   fillchar(b,sizeof(b),0);
  279.   b.exponent := r.exponent;
  280.   move(r.mantissa[5],b.mantissa[5],3);
  281.   RealtoBfloat4 := true;
  282. end;
  283.  
  284. Function RealtoBFloat8(rp : real; var b:bfloat8) : Boolean;
  285. var
  286.  r : TurboReal absolute rp;
  287. begin
  288.   fillchar(b,sizeof(b),0);
  289.   b.exponent := r.exponent;
  290.   move(r.mantissa[3],b.mantissa[3],5);
  291.   RealtoBfloat8 := true;
  292. end;
  293.  
  294. end.
  295.